#pragma once
#ifndef _WAVAUDIO_H
#define _WAVAUDIO_H

/*********************************************************************
 *****************************INCLUDES******************************
 ********************************************************************/
#include <Vector.h>
#include <iostream>
#include <numeric>
#include "tools.h"
// #include "wav.h"
#include "psram_manager.h"

/*********************************************************************
 * ***************************DEFINES*********************************
 *********************************************************************/
// Perfect combination: 10 7
#define MELS_NUM 10
#define SFTF_NUM 7
#define DATA_NUM 1000
#define FLOAT_BASE 10000

/*********************************************************************
 ****************************VARIABLES*******************************
 *********************************************************************/

struct wav_header_t {
	char chunkID[4];              //"RIFF" = 0x46464952
	unsigned long chunkSize;      //28 [+ sizeof(wExtraFormatBytes) + wExtraFormatBytes] + sum(sizeof(chunk.id) + sizeof(chunk.size) + chunk.size)
	char format[4];               //"WAVE" = 0x45564157
	char subchunk1ID[4];          //"fmt " = 0x20746D66
	unsigned long subchunk1Size;  //16 [+ sizeof(wExtraFormatBytes) + wExtraFormatBytes]
	unsigned short audioFormat;
	unsigned short numChannels;
	unsigned long sampleRate;
	unsigned long byteRate;
	unsigned short blockAlign;
	unsigned short bitsPerSample;
};

// (弃用)WAV文件头结构体
struct __attribute__((packed)) WAVHeader {
  // Chunk 1描述
  char chunkID[4];         // "RIFF"
  uint32_t chunkSize;      // 文件大小 - 8
  char format[4];          // "WAVE"

  // Sub-chunk 1描述
  char subchunk1ID[4];     // "fmt "
  uint32_t subchunk1Size;  // 16 for PCM
  uint16_t audioFormat;    // PCM = 1
  uint16_t numChannels;    // 1：单声道；2：立体声
  uint32_t sampleRate;     // 采样率
  uint32_t byteRate;       // sampleRate * numChannels * bitsPerSample/8
  uint16_t blockAlign;     // numChannels * bitsPerSample/8
  uint16_t bitsPerSample;  // 每个采样的比特数

  // Sub-chunk 2描述
  char subchunk2ID[4];     // "data"
  uint32_t subchunk2Size;  // 数据部分的大小
};

/*********************************************************************
**************************FUNCTIONS*********************************
 *********************************************************************/
class wavAudio
{
private:
	// wave's header
	unsigned int data_length;
	int format, channels, sample_rate, bits_per_sample, samples_num;

	// wave file's data
	// Vector<int16_t> data, process_data;
  	int16_t *data, *process_data;

	// max_data is max value in Spectrogram, and _per is the 10 percent of the max value
	int max_data = INT8_MIN;
	int _per = 0;
	int begin_clock = 0, end_clock = 0;
public:
	// character
	float duration = 0;
	int pitch = 0;
	int average_loudness = 0;
	int energy = 0;

	float mels_mean = 0;
	float mels_variance = 0;
	float mels_min = 0;
	float mels_max = 0;

	float sftf_real_mean = 0;
	float sftf_real_variance = 0;
	float sftf_real_max = 0;
	float sftf_real_min = 0;
	float sftf_imag_mean = 0;
	float sftf_imag_variance = 0;
	float sftf_imag_max = 0;
	float sftf_imag_min = 0;

	float* melsArray;
	float* sftfRealArray;
	float* sftfImagArray;
	
	wavAudio() {
		this->data_length = 1;
		this->format = 1;
		this->channels = 1;
		this->sample_rate = 1;
		this->bits_per_sample = 16;
		this->samples_num = 1;
    	this->data = Malloc(int16_t, this->samples_num);
	}
	wavAudio(const char* filepath) {
		printMemoryInfo("wavAudio init"); // print memory info
		this->readInfo(filepath);
	}
	void readInfo(const char* filepath); // read wave file information

	bool processdata(); // pre-processing;true 可继续执行;false 不可继续执行

	void calculatePitch(); // calculate the pitch

	void calculateAverageLoudness(); // calculate the average loudness

	void calculateTime(); // calculate the continue time

	void calculateEnergy(); // calculate the energy contained in audio

	void calculateSTFT();

	void calculateMelspectrogram();

	bool computeCharacter(); // compute character

	float* returnCharacter();

	~wavAudio();
};
#endif // WAVAUDIO_H